package com.app.db.datasource;


import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Configuration
@MapperScan(basePackages = DataSourceConstant.M2_PACKAGE, sqlSessionFactoryRef = "m2SqlSessionFactory")
/**
 * 数据源配置
 * @author liuli
 */
public class M2DataSourceConfig {
    /**M2*/
    @Value("${m2.datasource.url}")
    private String m2Url;
    @Value("${m2.datasource.username}")
    private String m2User;
    @Value("${m2.datasource.password}")
    private String m2Password;
    /**S2*/
    @Value("${s2.datasource.url}")
    private String s2Url;
    @Value("${s2.datasource.username}")
    private String s2User;
    @Value("${s2.datasource.password}")
    private String s2Password;
    /**驱动*/
    @Value("${db.mysql.driverClassName}")
    private String driverClass;
    /**pool*/
    @Value("${m2pool.datasource.maxActive}")
    private Integer maxActive;
    @Value("${m2pool.datasource.minIdle}")
    private Integer minIdle;
    @Value("${m2pool.datasource.initialSize}")
    private Integer initialSize;
    @Value("${m2pool.datasource.maxWait}")
    private Long maxWait;
    @Value("${m2pool.datasource.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;
    @Value("${m2pool.datasource.minEvictableIdleTimeMillis}")
    private Long minEvictableIdleTimeMillis;
    @Value("${m2pool.datasource.testWhileIdle}")
    private Boolean testWhileIdle;
    @Value("${m2pool.datasource.testWhileIdle}")
    private Boolean testOnBorrow;
    @Value("${m2pool.datasource.testOnBorrow}")
    private Boolean testOnReturn;
    @Value("${m2pool.datasource.maxPoolPreparedStatementPerConnectionSize}")
    private Integer maxPoolPreparedStatementPerConnectionSize;

    
    @Bean(name = "m2DataSource")
    public DataSource m2DataSource() {
        M2DynamicDataSource dynamicDataSource = M2DynamicDataSource.getInstance();
        DruidDataSource masterDataSource = new DruidDataSource();
        masterDataSource.setDriverClassName(driverClass);
        masterDataSource.setUrl(m2Url);
        masterDataSource.setUsername(m2User);
        masterDataSource.setPassword(m2Password);
        //连接池配置
        masterDataSource.setMaxActive(maxActive);
        masterDataSource.setMinIdle(minIdle);
        masterDataSource.setInitialSize(initialSize);
        masterDataSource.setMaxWait(maxWait);
        masterDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        masterDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        masterDataSource.setTestWhileIdle(testWhileIdle);
        masterDataSource.setTestOnBorrow(testOnBorrow);
        masterDataSource.setTestOnReturn(testOnReturn);
        masterDataSource.setValidationQuery("SELECT 'x'");
        masterDataSource.setPoolPreparedStatements(true);
        masterDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        //监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall
        try {
            masterDataSource.setFilters("stat,wall");
        } catch (SQLException e) {
        }
        DruidDataSource slaveDataSource = new DruidDataSource();
        slaveDataSource.setDriverClassName(driverClass);
        slaveDataSource.setUrl(s2Url);
        slaveDataSource.setUsername(s2User);
        slaveDataSource.setPassword(s2Password);
        //连接池配置
        slaveDataSource.setMaxActive(maxActive);
        slaveDataSource.setMinIdle(minIdle);
        slaveDataSource.setInitialSize(initialSize);
        slaveDataSource.setMaxWait(maxWait);
        slaveDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        slaveDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        slaveDataSource.setTestWhileIdle(testWhileIdle);
        slaveDataSource.setTestOnBorrow(testOnBorrow);
        slaveDataSource.setTestOnReturn(testOnReturn);
        slaveDataSource.setValidationQuery("SELECT 'x'");
        slaveDataSource.setPoolPreparedStatements(true);
        slaveDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            //通过别名的方式配置扩展插件，常用的插件有：
            //监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall
            slaveDataSource.setFilters("stat,wall");
        } catch (SQLException e) {
        }
        Map<Object,Object> map = new HashMap<>();
        map.put(DataSourceConstant.DB_MASTER2, masterDataSource);
        map.put(DataSourceConstant.DB_SLAVE2, slaveDataSource);
        dynamicDataSource.setTargetDataSources(map);
        // 默认数据源 MASTER
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
        return dynamicDataSource;
    }

    @Bean(name = "m2TransactionManager")
    public DataSourceTransactionManager m2TransactionManager() {
        return new DataSourceTransactionManager(m2DataSource());
    }

    @Bean(name = "m2SqlSessionFactory")
    public SqlSessionFactory m2SqlSessionFactory(@Qualifier("m2DataSource") DataSource m2DataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(m2DataSource);
        sessionFactory.setTypeAliasesPackage(DataSourceConstant.M2_PACKAGE);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(DataSourceConstant.M2_MAPPER_LOCATION));
        return sessionFactory.getObject();
    }


}